/*Group 04
Jose Renato da Silva Bonatelli 7288964
Matheus Martins Teixeira 7277482
Rafael de Paula Pinto Paravia 71522567*/

/*Given a graph, calculates the length of the diameter of a minimum diameter spanning tree */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#define INF (1<<29)
#define MIN( a , b ) ( (a<b) ? (a) : (b) )
#define EPS 1E-10
#define MAXV 1005

typedef struct str
{
    int duw;
    int dvw;
    int w;
} str;

typedef struct edge
{
    int u;
    int v;
} edge;

int cmp(const void * a, const void * b)  /*Comparison function*/
{
    if(((str*)a)->duw != ((str*)b)->duw) return ( ((str*)a)->duw < ((str*)b)->duw );
    else return ( ((str*)a)->dvw < ((str*)b)->dvw );
}
edge edges[(MAXV*(MAXV-1))>>1 ]; /*Vector of edges*/
int adj[MAXV][MAXV];    /*Adjacenty Matrix*/
int dist[MAXV][MAXV];   /*Minimal Distance Matrix (after Floyd Warshall)*/
int n,m;                /*n = vertexes / m = edges*/

double D()  /*Diameter*/
{
    int i,j,k,w,u,v,i1,i2;          /*Iterators*/
    str s[MAXV];
    double Ey = INF;
    double answ = INF;              /*Answer*/
    double upper_bound,lower_bound,f1,f2,mean;/*Variables for binary search*/

    /*Floyd Warshall Algorithm*/
    for(k=0; k<n; k++)
        for(i=0; i<n; i++)
            for(j=0; j<n; j++)
                dist[i][j] = MIN ( dist[i][j], dist[i][k] + dist[k][j]);
    /*dist[i][j] now has the minimum distance from each vertex to each vertex*/

    /*Running over all the edges (u,v)*/
    for(k=0; k<m; k++)
    {
        u = edges[k].u;
        v = edges[k].v;
        Ey = INF;
        /*Phase One*/
        /*Getting the minimum distance from vertexes u and v to all vertexes w*/
        for(w=0; w<n; w++)
        {
            s[w].duw = dist[u][w];
            s[w].dvw = dist[v][w];
            s[w].w = w;
        }
        qsort(s,n,sizeof(str),cmp);    /*Ordering s*/
        /*Phase Two*/
        i1 = 0;
        i2 = 1;
        while(i2 < n )
        {
            if(s[i1].dvw > s[i2].dvw)
            {
                i2++;
                continue;
            }
            /*Binary Search to find mean*/
            upper_bound = adj[u][v];
            lower_bound = 0.0;
            while(fabs(upper_bound-lower_bound)>EPS)
            {
                mean = (upper_bound+lower_bound)/2.0;
                f1 = fmin( mean + s[i1].duw , adj[u][v] - mean + s[i1].dvw);
                f2 = fmin( mean + s[i2].duw , adj[u][v] - mean + s[i2].dvw);
                if(f1>f2) lower_bound = mean;
                else upper_bound = mean;
            }
            /*By the end of the loop, mean is the absolute center of edge(u,v)(guessing hospital location)
            and f1=f2=distance from the hospital to the vertex w*/
            i1 = i2;
            i2++;
            if(f1<Ey)Ey = f1;/*Updating Ey if the distance was optimized*/
        }
        /*The answer is the biggest distance of a vertex w to the best location of the hospital*/
        if(answ>Ey)answ = Ey;
    }
    return answ;
}
int main (void)
{
    int i,j,k;

    memset(adj, 0, sizeof(int) * MAXV * MAXV); /*Initializating matrix adj*/
    scanf(" %d %d ",&n,&m);/*Reading the number of joints and streets(vertexes,edges)*/

    /*Initializating matrix dist.Setting distance to a big value*/
    for(i=0; i<n; i++)
        for(j=0; j<n; j++)
        {
            if(i!=j)dist[i][j]=INF; /*Distance of vertex i to j = "infinity"*/
            else dist[i][j] = 0;    /*Distance of vertex i to i = 0*/
        }

    /*Reading input*/
    for(k=0; k<m; k++)              /*For all edges*/
    {
        scanf(" %d %d ",&i,&j);     /*Edge(i,j)*/
        i--;
        j--;                    /*Starting at position zero instead of one*/
        edges[k].u=i;
        edges[k].v=j;  /*Saving the edge*/
        scanf(" %d ",&adj[i][j]);   /*Reading weight(i,j)*/
        dist[j][i] = dist[i][j] = adj[j][i] = adj[i][j];
    }
    printf("%g\n",D());/*Output*/
    return 0;
}

